use std::future::Future;

use serde::{Deserializer, Serializer};
use sqlx::{Arguments, Encode, Executor, FromRow, MySqlPool, Row, Type};
use sqlx::database::HasArguments;

use crate::ctx::res::Paging;

#[derive(rocket_db_pools::Database)]
#[database("mor_testing")]
pub struct MorTesting(MySqlPool);

trait Pageable {
    fn pageable<'e, 'c, F, R, E, P, DB>(self, executor: E, sql: &str, paging: Paging, param: Vec<P>)
        where
            F: std::future::Future<Output=R>,
            R: for<'r> FromRow<'r, DB::Row> + std::marker::Send + Unpin,
            E: Executor<'c, Database=DB>,
            P: std::marker::Send + for<'r> sqlx::Encode<'r, DB> + Type<DB>,
            DB: sqlx::Database;
}

pub struct QueryHelper;


impl Pageable for QueryHelper {
    #[inline]
    fn pageable<'e, 'c, F, R, E, P, DB>(self, executor: E, sql: &str, paging: Paging, param: Vec<P>) where F: Future<Output=R>, R: for<'r> FromRow<'r, DB::Row> + Send + Unpin, E: Executor<'c, Database=DB>, P: Send + for<'r> Encode<'r, DB> + Type<DB>, DB: sqlx::Database {
        let mut query_as = sqlx::query_as::<DB, R>(sql);
        for item in param {
            query_as = query_as.bind(item);
        }
        query_as.fetch_all(executor);
    }
}